package com.veromca.transaction.service;

import com.veromca.transaction.mapper.AccountMapper;
import com.veromca.transaction.po.AccountPO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @Description: 事务传播机制类型测试服务B
 * @Author: liusongqing
 * @CreateDate: 2019/12/08
 * @UpdateUser:
 * @UpdateDate:
 * @Copyright:
 * @UpdateRemark:
 * @Version: 0.2
 */
@Service
public class PropagationBService {

    @Autowired
    private AccountMapper accountMapper;

    /**
     * 无事务支持
     * @param accounts
     */
    public void insertAccounts(List<AccountPO> accounts) {
        for (AccountPO account : accounts) {
            accountMapper.insert(account);
            //if (true) throw new IllegalArgumentException("出异常了");
        }
    }

    /**
     * 默认事务
     * @param accounts
     */
    @Transactional
    public void insertAccountsTransaction(List<AccountPO> accounts) {
        for (AccountPO account : accounts) {
            accountMapper.insert(account);
            if (true) throw new IllegalArgumentException("出异常了");
        }
    }

    /**
     * 支持当前事务，如果当前没有事务，则新建事务
     * 如果当前存在事务，则加入当前事务，合并成一个事务
     *
     * @param accounts
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void insertAccountsTransactionRequired(List<AccountPO> accounts) {
        for (AccountPO account : accounts) {
            accountMapper.insert(account);
        }
    }

    /**
     * 新建事务，如果当前存在事务，则把当前事务挂起
     * 这个方法会独立提交事务，不受调用者的事务影响，父级异常，它也是正常提交
     *
     * @param accounts
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void insertAccountsTransactionRequiredNew(List<AccountPO> accounts) {
        for (AccountPO account : accounts) {
            accountMapper.insert(account);
        }
    }

    /**
     * 如果当前存在事务，则在嵌套事务内执行。如果当前没有事务，则新建事务
     * 如果当前存在事务，它将会成为父级事务的一个子事务，方法结束后并没有提交，只有等父事务结束才提交
     * 如果它异常，父级可以捕获它的异常而不进行回滚，父级正常提交，而它回滚事务不提交
     * 但如果父级异常，它必然回滚，这就是和 REQUIRES_NEW 的区别
     *
     * @param accounts
     */
    @Transactional(propagation = Propagation.NESTED)
    public void insertAccountsTransactionNested(List<AccountPO> accounts) {
        for (AccountPO account : accounts) {
            accountMapper.insert(account);
            if (true) throw new IllegalArgumentException("出异常了");
        }
    }

    /**
     * 如果当前存在事务，则加入事务
     * 如果当前不存在事务，则以非事务方式运行，这个和不写没区别
     *
     * @param accounts
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    public void insertAccountsTransactionSupport(List<AccountPO> accounts) {
        for (AccountPO account : accounts) {
            accountMapper.insert(account);
            if (true) throw new IllegalArgumentException("出异常了");
        }
    }

    /**
     * 以非事务方式运行
     * 如果当前存在事务，则把当前事务挂起
     *
     * @param accounts
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void insertAccountsTransactionNotSupport(List<AccountPO> accounts) {
        for (AccountPO account : accounts) {
            accountMapper.insert(account);
            if (true) throw new IllegalArgumentException("出异常了");
        }
    }

    /**
     * 如果当前存在事务，则运行在当前事务中
     * 如果当前无事务，则抛出异常，也即父级方法必须有事务
     *
     * @param accounts
     */
    @Transactional(propagation = Propagation.MANDATORY)
    public void insertAccountsTransactionMandatory(List<AccountPO> accounts) {
        for (AccountPO account : accounts) {
            accountMapper.insert(account);
            if (true) throw new IllegalArgumentException("出异常了");
        }
    }

    /**
     * 以非事务方式运行，如果当前存在事务，则抛出异常
     *
     * @param accounts
     */
    @Transactional(propagation = Propagation.NEVER)
    public void insertAccountsTransactionNever(List<AccountPO> accounts) {
        for (AccountPO account : accounts) {
            accountMapper.insert(account);
            if (true) throw new IllegalArgumentException("出异常了");
        }
    }

}
